<?php

class AdminController extends Controller {

	// Helper auxiliar de autenticação
	protected $auth;
	
	// Define o menu exibido
	// Menu icon: <img src="#{view.base}/web-files/images/icons/black/32/_c_#{view.controller}.png" alt="#{view.rotulo}" />
	protected $mainMenu = array(
				array( "controller" => "cliente", "rotulo" => "Clientes" ),
				array( "controller" => "dependente", "rotulo" => "Dependentes" ),
				//array( "controller" => "reserva", "rotulo" => "Reservas" ),
				array( "controller" => "condominio", "rotulo" => "Condomínio" ),
				//array( "controller" => "conta", "rotulo" => "Contas" ),
				//array( "controller" => "areaLazer", "rotulo" => "Áreas de Lazer" ),
				array( "controller" => "permissao", "rotulo" => "Permissões" )
	);
	
	protected $notItemMenu = array(
				array( "controller" => "boleto", "rotulo" => "Boletos" ),
				array( "controller" => "relatorio", "rotulo" => "Relatórios" )
	);
	
	protected $basicSystem = array(
				array( "controller" => "ajax", "rotulo" => "Ajax", "checked.todas" => "checked", "check.disabled" => "disabled" )
	);
	
	public function __construct() {
		parent::__construct();
		$this->auth = new AuthHelper();
	}
	
	// Antes de executar a action
	protected function before() {
		parent::before();
		// Faz verificações de segurança
		$this->beforeWithSecurity();
		// Seta dados
		$this->template->title = "Aracon - Administração, Contabilidade e Sistemas";
		$this->template->set("session.nome", $this->auth->getUserData("nome"));
		$this->template->set("session.perfil", TipoPermissaoModel::findNomePermissaoById($this->auth->getUserData("tipo_permissao_id")) );
		$this->template->set("footer", "Copyright 2012. Aracon - Administração, Contabilidade e Sistemas. Todos os direitos reservados.");
		// Monta menu
		$menu = $this->preparaMenu();
		$this->template->set("menu.li",$menu);
		// Monta bread crumb
		$breadCrumb = $this->preparaBreadCrumb();
		$this->template->set("breadcrumb.li",$breadCrumb);
	}
	
	// Depois de executar a action
	protected function after() {
		parent::after();
	}
	
	// Verificações de segurança
	protected function beforeWithSecurity() {
		// Verifica se o usuário se autenticou no banco
		$this->auth
				->setLogoutControllerAction("admin","logout")
				->checkLogin();
		// Verifica se o perfil do usuário está ativo
		$tipoPermissaoModel = new TipoPermissaoModel();
		$tipoPermissao = $tipoPermissaoModel->findById( $this->auth->getUserData("tipo_permissao_id") );
		if( $tipoPermissao['ativo'] == 0 && !$this->isAdministrador() )
			$this->auth
					->setLogoutControllerAction("welcome","index/error/perfilOff")
					->logout();
		// Checa as permissões do usuário e adiciona Growl Messages
		$this->checkPermissao();
	}
	
	// Verifica se o usuário logado é administrador
	protected function isAdministrador() {
		return ($this->auth->getUserData("tipo_permissao_id") == 0);
	}
	
	// ...
	protected function getIdFrom($strCamp="id") {
		$idParam = null;
		if( $this->isAdministrador() || $this->containsParam( $strCamp ) ){
			$idParam = $this->getParamId( $strCamp );
		}else if( $strCamp != "" ) {
			$idParam = $this->auth->getUserData( $strCamp ) ;
		}
		return $idParam;
	}
	
	//
	protected function testIsValidId($id) {
		return ( $id != null && is_numeric($id) );
	}
	
	// Adiciona avisos à pilha de exibição 
	protected function addGrowlMsgs($param) {
		$erroMsgs = $this->auth->getUserExtra("growlMsgs");
		if( $erroMsgs == null )
			$erroMsgs = array();
		$erroMsgs[] = $param;
		$this->auth->setUserExtra("growlMsgs", $erroMsgs);
	}
	
	// Adiciona array de avisos à pilha de exibição 
	protected function addAllGrowlMsgs($arrParams=array()) {
		$erroMsgs = $this->auth->getUserExtra("growlMsgs");
		if( is_array($arrParams) ){
			if( $erroMsgs == null )
				$erroMsgs = $arrParams;
			else
				$erroMsgs = array_merge($erroMsgs, $arrParams); 
		}else if( $erroMsgs == null ){
			$erroMsgs = array();
		}
		$this->auth->setUserExtra("growlMsgs", $erroMsgs);
	}
	
	// Recupera a pilha de avisos para exibição 
	protected function getAllGrowlMsgs() {
		$erroMsgs = $this->auth->getUserExtra("growlMsgs");
		if( $erroMsgs == null )
			return "";
		$this->auth->cleanParam("growlMsgs");
		return implode('","', $erroMsgs);
	}
	
	// Cria array baseado em mainMenu
	protected function createArrayControllerRotulo() {
		$response = array();
		$allControllers = array_merge($this->mainMenu, $this->notItemMenu, $this->basicSystem);
		foreach ( $allControllers as $menu )
			$response[ $menu['controller'] ] = $menu['rotulo'];
		return $response;
	}
	
	// Redireciona acessos indevidos 
	protected function redirecionaAcessoIdInvalido($area, $url, $break=false, $redirect=true) {
		$this->addGrowlMsgs( Messages::get("idInvalido", array( "{objeto}" => $area )) );
		if( $redirect || $break ) $this->redirect->goToUrl( $url );
		if( $break ) exit();
	}
	
	// Verificacão auxiliar para $permissoesController->inBasicSystem($controller);
	protected final function containsBasicSystem($controller) {
		foreach ($this->basicSystem as $bs)
			if( $controller == $bs['controller'] )
				return true;
		return false;
	}
	
	// Private section ============================================================================
	
	// Verifica se há permissão de acesso à área atual do sistema
	private function checkPermissao() {

		$this->template->set("msgs.growl", $this->getAllGrowlMsgs());
		
		if ( !$this->isAdministrador() && ($this->getController() != 'main') && ($this->getController() != 'admin') ) {
			
			$className = ucfirst( $this->getController() )."Controller";
			if( class_exists($className) ){
			
				$permissaoModel = new PermissaoModel();
				$class = new ReflectionClass( $className );
				
				if( $class->implementsInterface('ItemMenu') ){
				
					if( !$permissaoModel->isValid($this->auth->getUserData("tipo_permissao_id"), $this->getController(), $this->getAction()) )
						$this->acessoNegadoFuncionalidade();
					
				}else{
				
					if( !$permissaoModel->hasPermission($this->auth->getUserData("tipo_permissao_id"), $this->getController()) )
						$this->acessoNegadoFuncionalidade();
					
				}
			
			}else{
				
				$this->addGrowlMsgs( Messages::get("controllerNaoExiste", array( "{objeto}" => $className )) );
				$this->redirect->goToHome();
				exit();
				
			}

		}

	}
	
	private function acessoNegadoFuncionalidade() {
		$map = $this->createArrayControllerRotulo();
		if( $this->getAction() != "index" ){
			$this->addGrowlMsgs( Messages::get( "acessoNegadoFuncionalidade", array( "{objeto}" => ucfirst($this->getAction()) . " " . $map[ $this->getController() ] ) ) );
			$this->redirect->goToController($this->getController());
		}else {
			$this->addGrowlMsgs( Messages::get( "acessoNegadoFuncionalidade", array( "{objeto}" => "Gerenciar " . $map[ $this->getController() ] ) ) );
			$this->redirect->goToHome();
		}
		exit();
	}

	private function getActionsController($controller) {
	
		$response = array();
		$api = new ReflectionClass( ucfirst($controller)."Controller" );
		$methods = $api->getMethods( ReflectionMethod::IS_PUBLIC );
		foreach($methods as $method){
			$action = $method->getName();
			// actions são verbos e terminam em 'r'
		    if( (substr($action, (strlen($action)-1), 1) == "r") && ($action != "getController") )
				$response[] =  array(
   								"controller.action.url" => $controller."/".$action, 
   								"action.label" => ucfirst($action)." ".ucfirst($controller) 
				);
		}
		return $response;
		
	}
	
	// Constrói o menu para exibição, marcando o ativo
	private function preparaMenu() {
		
		$menus = $this->auth->getUserExtra("menus");
		
		if( $menus == null ){
			
			$menus = array(
				array( "controller" => "main", "rotulo" => "Início" )
			);
			
			if( !$this->isAdministrador() ){
				
				$menus[0] = array_merge( $menus[0], array( "actions.ul" => "", "menu.url" => BASE ) );
				
				$tipoPermissao = $this->auth->getUserData("tipo_permissao_id");
				$permissaoModel = new PermissaoModel();
				$permissoes = $permissaoModel->findAndOrderBy( array( "tipo_permissao_id" => $tipoPermissao ), "controller" );
			
				$allMenus = array_merge($this->mainMenu,$this->notItemMenu);
				
			   	// percorre permissoes
	   			foreach( $permissoes as $indexPermissao => $permissao ){
					// precorre os menus
					foreach($allMenus as $indexMenu => $menu){
		   				// adiciona aos menus o controller que estah em 'permissao' e em 'allMenus'
		   				if( $permissao['controller'] == $menu['controller'] ){
		   					$actions = explode("-", $permissao["actions"]);
		   					if( count( $actions ) >= 1 && $actions != "todas" ){
		   						$actionsSubmenu = array();
		   						foreach ( $actions as $action ){
			   						if( !in_array($action, array("index", "apagar", "editar")) ){
			   							$actionsSubmenu[] = array( 
			   								"controller.action.url" => $permissao['controller']."/".$action, 
			   								"action.label" => ucfirst($action)." ".ucfirst($permissao['controller']) 
			   							);
			   						}
		   						}
		   						$viewSubmenu = new View("main/submenu_ul");
		   						$viewSubmenu->set("actions", ViewList::merge("main/submenus_li", $actionsSubmenu));
		   						$menu["actions.ul"] = $viewSubmenu->output();
		   						$menu["menu.url"] = "#";
		   					}else{
		   						$actionsSubmenu = $this->getActionsController($permissao['controller']);
		   						$viewSubmenu = new View("main/submenu_ul");
		   						$viewSubmenu->set("actions", ViewList::merge("main/submenus_li", $actionsSubmenu));
		   						$menu["actions.ul"] = $viewSubmenu->output();
		   						$menu["menu.url"] = "#";
		   					}
		   					$menus[] = $menu;
		   					break;
		   				}
		   			}
				}
			
			}else{
				
				$tmp = $menus[0];
				$menus = $this->mainMenu;
				array_unshift($menus, $tmp);
				$tmp = array_merge($menus,$this->notItemMenu);
				$menus = $tmp;
				
			}
	
			$this->auth->setUserExtra("menus", $menus);
		}

		// seleciona o menu do controller atual
		for ($i = 0; $i < count($menus); $i++) {
			$controller = $menus[$i]["controller"];
			$menus[$i]["class"] = ($this->getController() == $controller) ? "class=\"active\"" : "";
		}
		
		$menuSite = ViewList::merge( ($this->isAdministrador() ? "main/menu_li" : "main/menu-submenus_li"), $menus);
		return $menuSite;
	}
	
	// Constrói o bread crumb, marcando o ativo
	private function preparaBreadCrumb() {
		
		$arr = array(
			array( "image" => "home", "rotulo" => "Início", "uri" => "main" )
		);
		
		if( $this->getController() != "main" ){
			$controller = $this->getController();
			$rotuloController = "";
			$menus = array_merge($this->mainMenu,$this->notItemMenu);
			foreach ($menus as $index => $menu)
				if( $controller == $menu['controller'] ){
					$rotuloController = $menu['rotulo'];
					break;
				}
			$arr[] = array( "rotulo" => $rotuloController, "uri" => $controller );
			/*$action = $this->getAction();
			if ( $action != "index" ){
				$breadCrumbAction = ucfirst($action)." ".$rotuloController;
				//$arr[] = array( "rotulo" => $breadCrumbAction, "uri" => $controller );
			}*/
		}
		
		// seleciona o breadcrumb do controller/action atual
		for ($i = 0; $i < count($arr); $i++) 
			$arr[$i]["class"] = (($i+1) == count($arr)) ? "class=\"active\"" : "";
			
		$breadCrumb = ViewList::merge("main/breadcrumb_li", $arr);
		return $breadCrumb;
	}
	
	// Public section =============================================================================
	
	// Desconecta o usuário do sistema
	public final function logout() {
		$this->addGrowlMsgs("");
		$this->auth
				->setLogoutControllerAction("welcome","index")
				->logout();
	}
	
	public function listar() {}
	public function ver() {}
	// Método escrito para ser herdado pelos filhos
	public function index_action() {
		
		if( $this->isAdministrador() ){
			$this->listar();
		}else {
			$permissaoModel = new PermissaoModel();
			$permissoes = $permissaoModel->find( 
				array( 
					"tipo_permissao_id" => $this->auth->getUserData("tipo_permissao_id"),
					"controller" => $this->getController() 
				)
			);
			if( count($permissoes) >= 1 )
				$permissoes = explode("-", $permissoes[0]["actions"]);
			else 
				$permissoes = array();
			if( in_array("listar", $permissoes) )
				$this->listar();
			else
				$this->ver();
		}
		
	}
	
}

?>